package com.cgy.utils.netx.ssh.server;

import com.cgy.utils.netx.config.ServerConfig;
import com.cgy.utils.netx.server.INetworkServerLibrary;
import com.google.common.base.Preconditions;
import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.command.Command;
import org.apache.sshd.server.command.CommandFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.shell.ProcessShellFactory;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Paths;

/**
 * @author CHTK
 */
public class SshServer implements INetworkServerLibrary<org.apache.sshd.server.SshServer> {

    private org.apache.sshd.server.SshServer sshServer;

    @Override
    public INetworkServerLibrary<org.apache.sshd.server.SshServer> config(ServerConfig serverConfig) {

        Preconditions.checkArgument(null != serverConfig);
        Preconditions.checkArgument(serverConfig.getPort() > 0 );

        // 禁止 bouncy castle，避免版本冲突
        System.setProperty("org.apache.sshd.registerBouncyCastle", "false");
        // SSH服务
        this.sshServer = org.apache.sshd.server.SshServer.setUpDefaultServer();

        if (SecurityUtils.isBouncyCastleRegistered()) {
            // 保存会话安全校验信息，key.pem和key.ser为文件名
            sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("key.pem")));
        }
        else {
            sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("key.ser")));
        }
        // 指定提供ssh服务的IP
        sshServer.setHost("0.0.0.0");
        // 指定ssh服务的端口
        sshServer.setPort(serverConfig.getPort());
        // 指定密码认证
        sshServer.setPasswordAuthenticator(
                new PasswordAuthenticator() {
                    @Override
                    public boolean authenticate(String username, String password,
                                                ServerSession session) {
                        System.out.println(">>>>>>用户名：" + username);
                        System.out.println(">>>>>>密码：" + password);
                        return serverConfig.getUsername().equals(username) && serverConfig.getPassword().equals(password);
                    }
                }
        );
        if (OsUtils.isUNIX()) {
            // 在Unix环境下，使用系统自带的sh来执行命令
            sshServer.setShellFactory(getShellFactory4Unix());
        } else {
            sshServer.setShellFactory(getShellFactory4Win());
        }
        //sshServer.setShellFactory(new ProcessShellFactory(new String[] { "D:\\cygwin\\bin\\bash", "-i", "-l" }));

        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
        sshServer.setCommandFactory(new ScpCommandFactory());
        sshServer.setCommandFactory(new CommandFactory() {
            @Override
            public Command createCommand(String command) {
                System.out.println(command);
                return new ProcessShellFactory(command.split(";")).create();
            }
        });
        sshServer.setFileSystemFactory(new FileSystemFactory() {
            @Override
            public FileSystem createFileSystem(Session session) throws IOException {
                return null;
            }
            // 如果需要使用ssh协议来提供文件下载、上传能力，则需要实现FileSystemFactory和SshFile接口

        });
        return this;
    }

    @Override
    public void start() throws Exception {
        sshServer.start();
    }

    @Override
    public void stop() throws Exception {
        sshServer.stop();
    }

    @Override
    public org.apache.sshd.server.SshServer getServer() throws Exception {
        return sshServer;
    }

    /**
     * * windows下的Shell
     * *
     * * @return
     */
    public static ProcessShellFactory getShellFactory4Win() {
        return new ProcessShellFactory(new String[]{"cmd.exe"});
    }


    /**
     * * unix下的Shell
     * *
     * * @return
     */
    public static ProcessShellFactory getShellFactory4Unix() {
        return new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"});
    }
}
